/*
 * This file intends to represent a generic combintation of elements related to
 * a specific element container. It must implement some specific type interface.
 */
#ifndef _GENERICCOMBINATION_H
#define _GENERICCOMBINATION_H

#include<map>  //Functions as an Hashtable
#include<vector>
#include<stack>

//Generic combination class description
//Container must have operator [] overloaded

template<typename T,typename container=std::vector<T> >
class GenericCombination{

      public:
             //---------------------------------------------------------------
             //Iterator implementation
             class iterator{
                   public:
                          //Contains a pointer to the permutation container
                          container operator*();
                          iterator operator++();
                          bool operator==(const iterator& it);
                          bool operator!=(const iterator& it);
                          iterator& operator=(const iterator& it);
                          
                          //Constructors
                          iterator(GenericCombination<T,container>& gP, int n, bool iAE = false);
                          iterator(const iterator& right);
                          //Iterator destructor
                          ~iterator();  
                          
                          void reset();  //To reset the iterator
                   private:
                           //Mantaining a reference to the permutation representation
                           GenericCombination<T,container>& elementSet;
                           int combinationNumber;
                           container state;  //Has the returning value
                           //Control stack
                           std::stack<typename std::map<int,T>::iterator>* stc;
                           int count;
                           
                           bool isBeforeStart;
                           bool isAfterEnd;
                           
                           bool increment();
             };
             //----------------------------------------------------------------------------------
             
             //Generic permutation container constructors
             GenericCombination(container& elementContainer);
             GenericCombination(container& elementContainer, int n);
             //Destuctor
             ~GenericCombination();
             
             //Obtains the correspondig iterators
             typename GenericCombination<T,container>::iterator begin();
             typename GenericCombination<T,container>::iterator end();
             
      private:
              std::map<T,int>* elementCont;  //Maintains an element counter
              int combinationNumber;  //Number of elements to permute
              
              //Initializes the map within the element count
              void initialize(container& elemContainer, int n);
};
#endif
